package com.example.shiroredis.security;

import com.example.shiroredis.entity.MpShiroPermsInfo;
import com.example.shiroredis.entity.MpUserInfo;
import com.example.shiroredis.service.inter.MpUserInfoService;
import com.example.shiroredis.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;

@Slf4j
public class UserRealm extends AuthorizingRealm {

    //必须设置lazy属性,否则可能导致userservice里面回滚出错
    @Autowired
    @Lazy
    private MpUserInfoService mpUserInfoService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 执行授权逻辑
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.warn("这是授权界面:[{}]", ShiroUtils.getUser().toString());
        log.info("执行授权逻辑");
        //设置授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        MpUserInfo mpUserInfo = (MpUserInfo) principalCollection.getPrimaryPrincipal();
        List<MpShiroPermsInfo> mpShiroPermsInfos = mpUserInfo.getMpShiroPermsInfoList();
        if (mpShiroPermsInfos != null && mpShiroPermsInfos.size() > 0) {
            for (MpShiroPermsInfo mpShiroPermsInfo : mpShiroPermsInfos) {
                info.addStringPermission(mpShiroPermsInfo.getPerms());
            }
            log.error("用户拥有的权限是:{}", info.getStringPermissions());
        } else {
            info.addStringPermission(null);
            log.error("用户没有任何拥有的权限");
        }
        return info;
    }

    /**
     * 执行认证逻辑
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.warn("执行认证逻辑");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String password = new String(token.getPassword());
        MpUserInfo mpUserInfo = mpUserInfoService.findUserAndPermsByUsername(token.getUsername());
        if (mpUserInfo == null) {
            return null;
        }
        if (mpUserInfo.getIsDelete() == 1) {
            throw new LockedAccountException("用户被锁定/被删除");
        }
        log.warn("当前用户登入信息是:{}", mpUserInfo);
        if ("-1".equals(password)) {
            //使用-1 相当于用的是微信code 登入,因为微信code是没有密码的,所以下面的校验密码可以直接从token里面拿,是必定密码正确的
            return new SimpleAuthenticationInfo(mpUserInfo, token.getPassword(), getName());
        }
        return new SimpleAuthenticationInfo(mpUserInfo, mpUserInfo.getPassword(), getName());
    }
}
